import type { ActionType, ProColumns } from '@ant-design/pro-table';
import { Button, Popconfirm, Table, message, Tree, Alert, Empty, Spin, Space, Tooltip, Tag, Popover, Transfer } from 'antd';
import React, { useRef, useState, useEffect } from 'react';

import { PageContainer } from '@ant-design/pro-layout';
import ProTable from '@ant-design/pro-table';
import ProCard from '@ant-design/pro-card';
import styles from './index.less';
import { useAccess, useIntl, useRequest } from 'umi';
import { DeleteOutlined, DownOutlined, FolderOutlined, FormOutlined, IdcardOutlined, PlusOutlined, TeamOutlined } from '@ant-design/icons';
import {
  getApiOrganizationTree as GetOrgs,
  getApiOrganizationDetailById as GetDetail,
  deleteApiOrganizationById as DeleteOrg,
  patchApiOrganizationByIdTreeByChangeid as UpdateTreeChange,
  getApiOrganizationByIdUsers as GetOrgUsers,
  getApiOrganizationByIdRoles as GetOrgRoles,
  putApiOrganizationByIdUsers as UpdateOrgUsers,
  deleteApiOrganizationByIdUsers as DeleteOrgUsers,
  putApiOrganizationByIdRoles as UpdateOrgRoles,
  deleteApiOrganizationByIdRoles as DeleteOrgRoles,
} from '@/services/furion-cms/organization';

import { getApiUserAll as GetUsers } from '@/services/furion-cms/user';
import { getApiRoleAll as GetRoles } from '@/services/furion-cms/role';

import type { DataNode } from 'antd/lib/tree';
import { DetailViewer } from './components/orgDetail';
import PermissionsDefinition from '@/permissionsDefinition';
import { useCustomAccess } from '@/components/CustomAccess';

const OrganizationManager: React.FC = () => {
  const actionRef = useRef<ActionType>();
  const access = useAccess();
  const AccessButton = useCustomAccess(Button);
  const AccessConfirm = useCustomAccess(Popconfirm);
  /**
   * @en-US International configuration
   * @zh-CN 国际化配置
   * */
  const intl = useIntl();

  const [tableTabKey, setTableTabKey] = useState<string>('users');
  const [treeData, setTreeData] = useState<DataNode[]>([]);
  const [selectedKeys, setSelectedKeys] = useState<string[]>([]);
  const [refreshLoading, setRefreshLoading] = useState<boolean>(false);
  const [detailVisible, setDetailVisible] = useState(false);
  const [relatedConfigureVisible, setRelatedConfigureVisible] = useState(false);
  const [relatedConfigureLoading, setRelatedConfigureLoading] = useState(false);
  const [detail, setDetail] = useState<API.OrgDetailDto>();
  const [distributionData, setDistributionData] = useState<APP.DistributionData[]>();
  const [targetKeys, setTargetKeys] = useState<string[]>([]);
  const [defaultTargetKeys, setDefaultTargetKeys] = useState<string[]>([]);

  const { data, error, loading } = useRequest(GetOrgs);

  const formattedDataHandle = (inputs: API.OrgDto[]): DataNode[] => {
    return inputs.map(m => ({ icon: <FolderOutlined />, title: m.name!, key: m.id!, children: formattedDataHandle(m.children ?? []) }));
  }

  useEffect(() => {
    console.log('setTreeData', data);
    setTreeData(formattedDataHandle(data ?? []));
  }, [data, loading]);// eslint-disable-line react-hooks/exhaustive-deps

  useEffect(() => {
    (async () => {
      try {
        let result: { success?: boolean, data?: any[], errorMessage?: string };
        if (tableTabKey === 'roles') {
          result = await GetRoles();
        } else {
          result = await GetUsers();
        }
        setDistributionData(result.data?.map(m => ({ key: m.id, title: m.name ?? m.nickName, description: m.name ?? m.nickName })));
      } catch { }
    })();
  }, [tableTabKey]);

  useEffect(() => setRelatedConfigureVisible(false), [tableTabKey, selectedKeys, treeData]);

  const onDrop = async (info: any) => {
    const dropKey = info.node.key;
    const droptitle = info.node.title;
    const dragKey = info.dragNode.key;
    const dragTitle = info.dragNode.title;
    const dropPos = info.node.pos.split('-');
    const dropPosition = info.dropPosition - Number(dropPos[dropPos.length - 1]);

    try {
      const { dropToGap } = info;
      setRefreshLoading(true);
      const result = await UpdateTreeChange({
        id: dragKey,
        changeid: dropKey,
        droptogap: dropToGap
      });
      setTreeData(formattedDataHandle(result.data ?? []));
    } catch { }
    setRefreshLoading(false);

    console.log('onDrop', info);
    console.log('onDrop', dropKey, droptitle, dragKey, dragTitle, dropPos, dropPosition);

  };

  const handleOrgNodeDelete = async (id: string) => {
    try {
      const result = await DeleteOrg({ id });
      const orgTreeData = formattedDataHandle(result.data ?? []);
      // 延迟100毫秒设置状态值避免出现popconfirm带来的内存泄漏问题
      setTimeout((e) => {
        setTreeData(e[0]);
      }, 100, [orgTreeData]);
    } catch { }
  }

  const handleOrgDetail = async (id: string) => {
    try {
      const result = await GetDetail({ id });
      setDetail(result.data);
      setDetailVisible(true);
    } catch {
      message.error(intl.formatMessage({
        id: "pages.common.error",
        defaultMessage: "系统错误"
      }));
    }
  }

  const getColumns = (key: string): ProColumns[] => {
    const columnsActive = {
      users: () => [
        {
          title: intl.formatMessage({
            id: 'pages.user.nickName',
            defaultMessage: '昵称'
          }),
          dataIndex: 'avatar',
          valueType: 'avatar',
          sorter: true,
          search: false,
          render: (dom: any, entity: any) => (
            <Space>{dom}{entity.nickName}</Space>
          )
        },
        {
          title: intl.formatMessage({
            id: 'pages.user.email',
            defaultMessage: '电子邮件'
          }),
          dataIndex: 'email',
          search: false,
        },
        {
          title: intl.formatMessage({
            id: 'pages.user.phoneNumber',
            defaultMessage: '手机号'
          }),
          dataIndex: 'phoneNumber',
          search: false,
        },
      ],
      roles: () => [
        {
          title: intl.formatMessage({
            id: 'pages.role.name',
            defaultMessage: '名称'
          }),
          dataIndex: 'name',
          search: false,
          render: (_: any, entity: API.RoleDto) => {
            return <Space>
              <span>{entity.name}</span>
              {entity.hasSeed && <Tag color="magenta">{intl.formatMessage({ id: "pages.role.type.inner", defaultMessage: "内置" })}</Tag>}
              {entity.isDefault && <Tag color="blue">{intl.formatMessage({ id: "pages.role.type.default", defaultMessage: "默认" })}</Tag>}
            </Space>;
          }
        },
        {
          title: intl.formatMessage({
            id: 'pages.role.description',
            defaultMessage: '描述'
          }),
          dataIndex: 'description',
          search: false,
        },
      ]
    }
    return columnsActive[key] && columnsActive[key]();
  }

  const handleOrgRelatedConfigure = async () => {
    setRelatedConfigureLoading(true);
    const [id] = selectedKeys;
    //targetKeys
    try {
      if (tableTabKey === 'roles') {
        await UpdateOrgRoles({ id }, targetKeys as any[]);
      }
      else {
        await UpdateOrgUsers({ id }, targetKeys as any[]);
      }
    } catch { }
    actionRef.current?.reload();
    setRelatedConfigureLoading(false);
    setRelatedConfigureVisible(false);
  }

  const popoverContent = (<>
    <Transfer
      titles={[
        intl.formatMessage({
          id: 'component.transfer.source',
          defaultMessage: '未分配'
        }),
        intl.formatMessage({
          id: 'component.transfer.target',
          defaultMessage: '已分配'
        })
      ]}
      dataSource={distributionData}
      targetKeys={targetKeys}
      onChange={(newTargetKeys, direction, moveKeys) => {
        console.log(newTargetKeys, direction, moveKeys);
        setTargetKeys(newTargetKeys);
      }}
      render={item => item.title}
      pagination
      showSearch
    />
    <Space style={{
      marginTop: 15,
      display: 'flex',
      justifyContent: 'flex-end',
    }}>
      <Button onClick={async () => {
        setRelatedConfigureVisible(false);
        setTargetKeys(defaultTargetKeys);
      }}>
        {intl.formatMessage({
          id: 'pages.common.confirm.cancel',
          defaultMessage: '取消'
        })}
      </Button>
      <Button disabled={targetKeys.length === 0} loading={relatedConfigureLoading}
        onClick={handleOrgRelatedConfigure}
        type="primary">{intl.formatMessage({
          id: 'pages.common.confirm.ok',
          defaultMessage: '确认'
        })}</Button>
    </Space>
  </>);

  const tableOperatePermissionRender = (tableType: string, selectedRowKeys: any[], onCleanSelected: () => void) => {
    let confirmProps: any = {};
    const orgId = selectedKeys?.[0];
    if (tableType === "users" && access.canOperatorItem(PermissionsDefinition.Organization.AssignOrgPerson)) {
      confirmProps = {
        onConfirm: async () => {
          try {
            await DeleteOrgUsers({ id: orgId }, selectedRowKeys);
            onCleanSelected();
            actionRef.current?.reload();
          } catch { }
        }
      }
    }
    else if (access.canOperatorItem(PermissionsDefinition.Organization.AssignOrgRole)) {
      confirmProps = {
        onConfirm: async () => {
          try {
            await DeleteOrgRoles({ id: orgId }, selectedRowKeys);
            onCleanSelected();
            actionRef.current?.reload();
          } catch { }
        }
      }
    }

    return (<Space size={16}>
      <Popconfirm
        title={intl.formatMessage({
          id: 'pages.common.batchDeletion.confirm',
          defaultMessage: '您是否确认删除选中的 {count} 项数据?'
        }, { count: selectedRowKeys.length })}
        {...confirmProps}
      >
        <a href="#">{intl.formatMessage({
          id: 'pages.common.batchDeletion',
          defaultMessage: '批量删除'
        })}</a>
      </Popconfirm>
    </Space>);
  };

  return (
    <PageContainer className={styles.main}
      breadcrumbRender={false}
      loading={loading}>
      <ProCard split="vertical">
        <ProCard
          title={intl.formatMessage({
            id: 'pages.org.tree',
            defaultMessage: "组织机构树"
          })}
          colSpan="420px"
          extra={(
            <AccessButton code={PermissionsDefinition.Organization.CreateOrg}
              type='primary'
              disabled={refreshLoading}
              icon={<PlusOutlined />}
              onClick={() => setDetailVisible(true)}>
              {intl.formatMessage({
                id: 'pages.org.tree.root.add',
                defaultMessage: '添加根机构'
              })}
            </AccessButton>
          )}
          headerBordered>
          {error && <Alert
            message={intl.formatMessage({
              id: "pages.common.error",
              defaultMessage: "系统错误"
            })}
            description={() => {
              const errorInfo = error as any;
              const { errorMessage } = errorInfo.data;
              return errorMessage;
            }}
            type="error"
            showIcon
          />}
          {treeData.length ? <Spin tip="loading..." spinning={refreshLoading}>
            <Tree
              showIcon
              switcherIcon={<DownOutlined />}
              className={styles.customTree}
              draggable={access.canOperatorItem(PermissionsDefinition.Organization.UpdateOrg)}
              defaultExpandAll
              blockNode
              selectedKeys={selectedKeys}
              onDrop={onDrop}
              treeData={treeData}
              titleRender={node => {
                return <>
                  {node.title}
                  {selectedKeys.includes(node.key as string) ? <Space size={0} className={styles.orgOperatePanel}>
                    <AccessButton code={PermissionsDefinition.Organization.CreateOrg}
                      tooltip={intl.formatMessage({ id: 'pages.org.tree.node.add', defaultMessage: '添加子节点' })}
                      type="link" size='small' icon={<PlusOutlined />} onClick={() => {
                        setDetail({
                          parentId: node.key as string
                        })
                        setDetailVisible(true);
                      }} />
                    <AccessButton code={PermissionsDefinition.Organization.UpdateOrg}
                      tooltip={intl.formatMessage({ id: 'pages.org.tree.node.edit', defaultMessage: '编辑' })}
                      type="link" size='small' icon={<FormOutlined />} onClick={() => handleOrgDetail(node.key as string)} />
                    <AccessConfirm code={PermissionsDefinition.Organization.DeleteOrg}
                      title={intl.formatMessage({
                        id: 'pages.org.tree.node.remove.confirm',
                        defaultMessage: '删除 {title} 节点时会同时删除子节点'
                      }, { title: node.title as string })}
                      onConfirm={() => handleOrgNodeDelete(node.key as string)}
                      destroyTooltipOnHide>
                      <Tooltip title={intl.formatMessage({ id: 'pages.org.tree.node.remove', defaultMessage: '删除' })}>
                        <Button type="link" size='small'
                          icon={<DeleteOutlined />}
                        //  onClick={() => setConfirmVisible(true)}
                        />
                      </Tooltip>
                    </AccessConfirm>
                  </Space> : ''}
                </>
              }}
              onSelect={(_selectedKeys, info) => {
                if (info.selected) {
                  setSelectedKeys(_selectedKeys as string[]);
                }
              }}
            />
          </Spin> : <Empty image={Empty.PRESENTED_IMAGE_SIMPLE} />}
        </ProCard>
        <ProCard bodyStyle={{ padding: 0 }}>
          {selectedKeys.length ? <ProTable
            rowKey="id"
            actionRef={actionRef}
            search={{ filterType: "light" }}
            rowSelection={{
              selections: [Table.SELECTION_ALL, Table.SELECTION_INVERT],
            }}
            toolbar={{
              menu: {
                type: 'tab',
                activeKey: tableTabKey,
                onChange: (key) => setTableTabKey(key as string),
                items: [
                  {
                    key: 'users',
                    label: <><TeamOutlined /> {intl.formatMessage({ id: 'pages.org.related.users', defaultMessage: '成员' })}</>,
                  },
                  {
                    key: 'roles',
                    label: <><IdcardOutlined /> {intl.formatMessage({ id: 'pages.org.related.roles', defaultMessage: '角色' })}</>,
                  },
                ]
              },
              style: {
                padding: '0px 15px',
                height: 65
              },
            }}
            tableAlertOptionRender={({ selectedRowKeys, onCleanSelected }) => tableOperatePermissionRender(tableTabKey, selectedRowKeys, onCleanSelected)}
            toolBarRender={() => [
              tableTabKey == "users" &&
              <Popover placement="bottomRight"
                title={intl.formatMessage({
                  id: 'pages.org.related.users.add',
                  defaultMessage: '分配成员'
                })}
                content={popoverContent}
                visible={relatedConfigureVisible}
                destroyTooltipOnHide>
                <AccessButton code={PermissionsDefinition.Organization.AssignOrgPerson}
                  key="primary"
                  type="primary"
                  icon={<PlusOutlined />}
                  disabled={selectedKeys.length === 0}
                  onClick={() => {
                    console.log('targetKeys', targetKeys);
                    setRelatedConfigureVisible(true);
                  }}
                >
                  {intl.formatMessage({
                    id: 'pages.org.related.users.add',
                    defaultMessage: '分配成员'
                  })}
                </AccessButton>
              </Popover>,
              tableTabKey == "roles" &&
              <Popover
                placement="bottomRight"
                title={intl.formatMessage({
                  id: 'pages.org.related.roles.add',
                  defaultMessage: '分配角色'
                })}
                content={popoverContent}
                visible={relatedConfigureVisible}
                destroyTooltipOnHide>
                <AccessButton code={PermissionsDefinition.Organization.AssignOrgRole}
                  key="primary"
                  type="primary"
                  icon={<PlusOutlined />}
                  disabled={selectedKeys.length === 0}
                  onClick={() => {
                    console.log('targetKeys', targetKeys);
                    setRelatedConfigureVisible(true);
                  }}
                >
                  {intl.formatMessage({
                    id: 'pages.org.related.roles.add',
                    defaultMessage: '分配角色'
                  })}
                </AccessButton>
              </Popover>
            ]}
            columns={getColumns(tableTabKey)}
            cardProps={{
              bodyStyle: { padding: '0px 0px 24px 0px' },
            }}
            pagination={false}
            params={{
              orgId: selectedKeys?.[0],
              type: tableTabKey,
            }}
            request={(params) => {
              const { orgId, type } = params;
              const handleData = (result: any) => {
                const tks = result.data?.map((m: any) => m.id) ?? [];
                setTargetKeys(tks);
                setDefaultTargetKeys(tks);
                return result;
              }
              if (orgId) {
                if (type === 'roles') {
                  return GetOrgRoles({ id: orgId }).then(handleData);
                }
                return GetOrgUsers({ id: orgId }).then(handleData);
              }
              return Promise.resolve({
                success: true,
                data: [],
              });
            }}
          /> : <Empty description={intl.formatMessage({
            id: 'pages.org.related.empty',
            defaultMessage: '请先选择组织机构'
          })} style={{
            padding: '100px 0'
          }} />}
        </ProCard>
      </ProCard>
      <DetailViewer
        recored={detail}
        modalVisible={detailVisible}
        onVisibleChange={(visit) => {
          setDetailVisible(visit);
          if (!visit) setDetail(undefined);
        }}
        onUpdate={datas => {
          setTreeData(formattedDataHandle(datas));
        }} />
    </PageContainer>
  )
};

export default OrganizationManager;

